package com.xu.cloud.common.sequence;

import com.xu.cloud.common.util.ApplicationContextUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;

/**
 * Redis自增
 *
 * @author xuguan
 * @since 2023/12/27
 */
public class RedisSequence implements ISequence {

    private static final int SEQUENCE_BIT = 8;
    private static final long SEQUENCE_MAX_NUM = BigDecimal.TEN.pow(SEQUENCE_BIT).longValue() - 1;
    private static final String SEQUENCE_KEY = "xu:cloud:sequence_generator";
    private static final NumberFormat fmt = new DecimalFormat("00000000");

    public long increment() {
        RedisTemplate<String, Object> redisTemplate = ApplicationContextUtil.getBean("redisTemplate", RedisTemplate.class);
        Assert.notNull(redisTemplate, "redisTemplate not allowed null");

        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();

        // 超出最大范围, 删除redis键
        Integer sequenceVal = (Integer) opsForValue.get(SEQUENCE_KEY);
        if (!ObjectUtils.isEmpty(sequenceVal) && sequenceVal >= SEQUENCE_MAX_NUM) {
            redisTemplate.delete(SEQUENCE_KEY);
        }

        Long incrSequence = opsForValue.increment(SEQUENCE_KEY);
        Assert.notNull(incrSequence, "incrSequence not allowed null");

        return incrSequence;
    }

    @Override
    public String nextId() {
        return fmt.format(this.increment());
    }
}
